home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / advanced97 / BUMP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  18.9 KB  |  856 lines

  1. #include <GL/glut.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <math.h>
  6. #include "texture.h"
  7.  
  8. /* Some <math.h> files do not define M_PI... */
  9. #ifndef M_PI
  10. #define M_PI 3.14159265358979323846
  11. #endif
  12.  
  13. #ifndef __sgi
  14. /* Most math.h's do not define float versions of the math functions. */
  15. #define sqrtf(x) (float)sqrt((x))
  16. #define cosf(x) (float)cos((x))
  17. #define sinf(x) (float)sin((x))
  18. #endif
  19.  
  20. int winWidth = 512;
  21. int winHeight = 512;
  22.  
  23. #ifndef FALSE
  24. enum {FALSE, TRUE};
  25. #endif
  26. enum {S, T}; /* make array indexing more intuitive */
  27. enum {X, Y, Z, W};
  28. enum {R, G, B, A};
  29. enum {DEFAULT_TEX, ACCUM_TEX, ADD_TEX, SUB_TEX}; /* texture names */
  30. enum {LIGHT_XY, LIGHT_Z, PGON}; /* what should move */
  31.  
  32. int dblbuf = TRUE;
  33. int accum = FALSE;
  34. int color = FALSE;
  35. int wire = FALSE;
  36. int textureOnly = FALSE;
  37. int lightOnly = FALSE;
  38. int bindtex = FALSE;
  39. int embossed = FALSE;
  40. int steps_xz = 20, steps_y = 20;
  41.  
  42. int texture_width;
  43. int texture_height;
  44.  
  45. /* is bumpmap shifting on? */
  46. int bumpEnabled = FALSE;
  47.  
  48. int move = LIGHT_XY;
  49.  
  50. /* current tangent vector */
  51. GLfloat curTangent[3];
  52.  
  53. /* current texture coordinate */
  54. GLfloat curTex[2];
  55.  
  56.  
  57. /* current normal */
  58. GLfloat curNormal[3];
  59.  
  60. /* current light position */
  61. GLfloat curLight[3];
  62. GLfloat lightpos[4] = {100.f, 100.f, 100.f, 1.f};
  63. GLfloat angles[2]; /* x and y angle */
  64.  
  65. unsigned *bumptex; /* pointer to bumpmap texture */
  66. GLfloat bumpscale = .39f; /* scale down bumpmap texture (a smidgen under .4) */
  67.  
  68. /* TEST PROGRAM */
  69.  
  70. #if !defined(GL_VERSION_1_1) && !defined(GL_VERSION_1_2)
  71. #define glBindTexture glBindTextureEXT
  72. #endif
  73.  
  74. #define CHECK_ERROR(str)                                           \
  75. {                                                                  \
  76.     GLenum error;                                                  \
  77.     if(error = glGetError())                                       \
  78.        printf("GL Error: %s (%s)\n", gluErrorString(error), str);  \
  79. }
  80.  
  81. void
  82. bumpEnable(void)
  83. {
  84.     bumpEnabled = TRUE;
  85. }
  86.  
  87. void
  88. bumpDisable(void)
  89. {
  90.     bumpEnabled = FALSE;
  91. }
  92.  
  93. void
  94. reshape(int wid, int ht)
  95. {
  96.     winWidth = wid;
  97.     winHeight = ht;
  98.     glViewport(0, 0, wid, ht);
  99. }
  100.  
  101.  
  102.  
  103. void
  104. mouse(int button, int state, int x, int y)
  105. {
  106.     if(state == GLUT_DOWN)
  107.     switch(button)
  108.     {
  109.     case GLUT_LEFT_BUTTON: /* move the light */
  110.         move = LIGHT_XY;
  111.         lightpos[X] = (x - winWidth/2) * 300.f/winWidth;
  112.         lightpos[Y] = (winHeight/2 - y) * 300.f/winHeight;
  113.         glutPostRedisplay();
  114.         break;
  115.     case GLUT_MIDDLE_BUTTON:
  116.         move = PGON;
  117.         angles[X] = (x - winWidth/2) * 180.f/winWidth;
  118.         angles[Y] = (y - winHeight/2) * 180.f/winHeight;
  119.         glutPostRedisplay();
  120.         break;
  121.     case GLUT_RIGHT_BUTTON: /* move the polygon */
  122.         move = LIGHT_Z;
  123.         lightpos[Z] = (winHeight/2 - y) * 300.f/winWidth;
  124.         glutPostRedisplay();
  125.         break;
  126.     }
  127. }
  128.  
  129. void
  130. motion(int x, int y)
  131. {
  132.     switch(move)
  133.     {
  134.     case LIGHT_XY:
  135.     lightpos[X] = (x - winWidth/2) * 300.f/winWidth;
  136.     lightpos[Y] = (winHeight/2 - y) * 300.f/winHeight;
  137.     glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  138.     glutPostRedisplay();
  139.     break;
  140.     case LIGHT_Z:
  141.     lightpos[Z] = (winHeight/2 - y) * 300.f/winWidth;
  142.     glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  143.     glutPostRedisplay();
  144.     break;
  145.     case PGON:
  146.     angles[X] = (x - winWidth/2) * 180.f/winWidth;
  147.     angles[Y] = (y - winHeight/2) * 180.f/winHeight;
  148.     glutPostRedisplay();
  149.     break;
  150.     }
  151. }
  152.  
  153.  
  154. /*
  155. ** Create a single component texture map
  156. */
  157. GLfloat *make_texture(int maxs, int maxt)
  158. {
  159.     int s, t;
  160.     GLfloat *texture;
  161.  
  162.     /* assumed format; LUMINANCE */
  163.     texture = (GLfloat *)malloc(maxs * maxt * sizeof(GLfloat));
  164.     for(t = 0; t < maxt; t++) {
  165.     for(s = 0; s < maxs; s++) {
  166.         texture[s + maxs * t] = ((s >> 3) & 0x1) ^ ((t >> 3) & 0x1);
  167.     }
  168.     }
  169.     return texture;
  170. }
  171.  
  172. /* get current light position in object space */
  173. void
  174. bumpLightPos(GLfloat *x, GLfloat *y, GLfloat *z)
  175. {
  176.     GLdouble mvmatrix[16];
  177.     GLint viewport[4];
  178.     static GLdouble projmatrix[16]; /* to make them zero */
  179.     GLfloat light[4];
  180.     GLdouble Ex, Ey, Ez;
  181.     GLdouble Ox, Oy, Oz;
  182.  
  183.     CHECK_ERROR("bumpLightPos");
  184.     glGetLightfv(GL_LIGHT0, GL_POSITION, light);
  185.     Ex = light[X]; Ey = light[Y]; Ez = (light[Z] + 1)/2.;
  186.  
  187.     CHECK_ERROR("bumpLightPos");
  188.     glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
  189.     
  190.     /* identity projection matrix */
  191.     projmatrix[0] = projmatrix[5] = projmatrix[10] = projmatrix[15] = 1.;
  192.  
  193.     /* identity viewport */
  194.     viewport[0] = viewport[1] = -1; 
  195.     viewport[2] = viewport[3] =  2;
  196.  
  197.     /*
  198.     ** use the inverse of the modelview matrix to
  199.     ** transform light from eye to object space
  200.     */
  201.     gluUnProject(Ex, Ey, Ez, mvmatrix, projmatrix, viewport, &Ox, &Oy, &Oz);
  202.  
  203.     *x = Ox; *y = Oy; *z = Oz;
  204.     CHECK_ERROR("bumpLightPos");
  205. }
  206.  
  207.  
  208. /* compute binormal from current normal and tangent vector, using cross prod */
  209. /* assuming normal and tangent are already normalized */
  210. void
  211. biNormal(GLfloat *x, GLfloat *y, GLfloat *z)
  212. {
  213.     /* normal <cross> tangent = binormal */
  214.  
  215.     *x = curNormal[Y] * curTangent[Z] - curNormal[Z] * curTangent[Y];
  216.     *y = curNormal[Z] * curTangent[X] - curNormal[X] * curTangent[Z];
  217.     *z = curNormal[X] * curTangent[Y] - curNormal[Y] * curTangent[X];
  218. }
  219.  
  220. void
  221. Normalize2f(GLfloat *x, GLfloat *y)
  222. {
  223.     GLfloat len;
  224.     len = *x * *x + *y * *y;
  225.     len = sqrtf(len);
  226.  
  227.     *x /= len;
  228.     *y /= len;
  229. }
  230.  
  231. /* rotate point by supplied rotatation matrix */
  232. void
  233. Rotate(GLfloat *rot, GLfloat *light, GLfloat *s, GLfloat *t)
  234. {
  235.     GLfloat r;
  236.     r = rot[3] * light[X] + rot[4] * light[Y] + rot[5] * light[Z];
  237.     if(r < 0.f) /* light below surface */
  238.     {
  239.     *s = 0.f;
  240.     *t = 0.f;
  241.     return;
  242.     }
  243.     *s = rot[0] * light[X] + rot[1] * light[Y] + rot[2] * light[Z];
  244.     *t = rot[6] * light[X] + rot[7] * light[Y] + rot[8] * light[Z];
  245.     Normalize2f(s, t);
  246. }
  247.  
  248.  
  249. /* find out where the current normal is */
  250. void
  251. bumpNormal3f(GLfloat x, GLfloat y, GLfloat z)
  252. {
  253.     curNormal[X] = x;
  254.     curNormal[Y] = y;
  255.     curNormal[Z] = z;
  256.     glNormal3f(x, y, z);
  257. }
  258.  
  259. void
  260. bumpTangent3f(GLfloat x, GLfloat y, GLfloat z)
  261. {
  262.     curTangent[X] = x;
  263.     curTangent[Y] = y;
  264.     curTangent[Z] = z;
  265. }
  266.  
  267. /* save the texture coordinate call; will shift to do bumpmapping */
  268. void
  269. bumpTexCoord2f(GLfloat s, GLfloat t)
  270. {
  271.     curTex[S] = s;
  272.     curTex[T] = t;
  273. }
  274.  
  275. /*
  276. ** use current tangent vector to compute texture coordinate shift
  277. ** then apply it by passing through vertex call
  278. */
  279. void
  280. bumpVertex3f(GLfloat x, GLfloat y, GLfloat z)
  281. {
  282.  
  283.     GLfloat Light[3]; /* light in tangent space */
  284.     GLfloat length;
  285.     GLfloat s, t; /* tranformed light, used to shift */
  286.     GLfloat rot[9]; /* rotation matrix (just enought for x and y */
  287.     GLfloat Bx, By, Bz; /* binormal axis */
  288.  
  289.     if(bumpEnabled)
  290.     {
  291.  
  292.     /* get current light position */
  293.     Light[X] = curLight[X];
  294.     Light[Y] = curLight[Y];
  295.     Light[Z] = curLight[Z];
  296.  
  297.     /* find light vector from vertex */
  298.     Light[X] -= x; Light[Y] -= y; Light[Z] -= z;
  299.  
  300.     length = 1.f/ sqrtf(Light[X] * Light[X] + 
  301.                 Light[Y] * Light[Y] +
  302.                 Light[Z] * Light[Z]);
  303.  
  304.     Light[X] *= length; Light[Y] *= length; Light[Z] *= length;
  305.  
  306.     /* create rotation matrix (rotate into tangent space) */
  307.     
  308.     biNormal(&Bx, &By, &Bz); /* find binormal axis */
  309.  
  310.     rot[0] = curTangent[X]; rot[1] = curTangent[Y]; rot[2] = curTangent[Z];
  311.     rot[3] = curNormal[X]; rot[4] = curNormal[Y]; rot[5] = curNormal[Z];    
  312.     rot[6] = Bx; rot[7] = By; rot[8] = Bz;
  313.  
  314.     Rotate(rot, Light, &s, &t);
  315.  
  316.     /* shift coordinates in opposite direction of desired texture shift */
  317.     glTexCoord2f(curTex[S] - s/texture_width, curTex[T] - t/texture_height);
  318.     }
  319.     else
  320.     glTexCoord2f(curTex[S], curTex[T]);
  321.  
  322.     glVertex3f(x, y, z); /* pass on the vertex call */
  323. }
  324.  
  325. void
  326. bumpBegin(GLenum prim)
  327. {
  328.     if(bumpEnabled)
  329.     {
  330.     /* get light position; map back from eye to object space */
  331.     bumpLightPos(&curLight[X], &curLight[Y], &curLight[Z]);
  332.     }
  333.     glBegin(prim);
  334. }
  335.  
  336. void draw(void)
  337. {
  338.     int i, j;
  339.     GLfloat Vx, Vy, Vz; /* vertex */
  340.     GLfloat Tx, Ty, Tz; /* tangent */
  341.     GLfloat Nx, Ny, Nz; /* normal */
  342.     GLfloat c, s; /* cos, sin */
  343.  
  344.     CHECK_ERROR("start of draw()");
  345.  
  346.  
  347.     Ny = 0.f;
  348.     Ty = 0.f;
  349.     /* v(i, j) v(i+1, j), v(i+1, j+1), v(i, j+1) */
  350.     bumpBegin(GL_QUADS);
  351.     for(j = 0; j < steps_y; j ++)
  352.     for(i = 0; i < steps_xz; i++) /* 180 -> 0 degrees */
  353.     {
  354.         /* v(i, j) */
  355.         c = cosf(M_PI * (1.f - (GLfloat)i/(steps_xz - 1)));
  356.         s = sinf(M_PI * (1.f - (GLfloat)i/(steps_xz - 1)));
  357.         Vx = 100 * c;
  358.         Vy = j * 200.f/steps_y - 100.f;
  359.         Vz = 100 * s - 100.f;
  360.         Nx = c;
  361.         Nz = s;
  362.         Tx = s;
  363.         Ty = -c;
  364.         bumpNormal3f(Nx, Ny, Nz);
  365.         bumpTangent3f(Tx, Ty, Tz);
  366.         bumpTexCoord2f(i/(GLfloat)steps_xz, j/(GLfloat)steps_y);
  367.         bumpVertex3f(Vx, Vy, Vz);
  368.  
  369.         /* v(i+1, j) */
  370.         c = cosf(M_PI * (1.f - (GLfloat)(i + 1)/(steps_xz - 1)));
  371.         s = sinf(M_PI * (1.f - (GLfloat)(i + 1)/(steps_xz - 1)));
  372.         Vx = 100 * c;
  373.         Vz = 100 * s - 100.f;
  374.         Nx = c;
  375.         Nz = s;
  376.         Tx = s;
  377.         Ty = -c;
  378.         bumpNormal3f(Nx, Ny, Nz);
  379.         bumpTangent3f(Tx, Ty, Tz);
  380.         bumpTexCoord2f((i + 1)/(GLfloat)steps_xz, j/(GLfloat)steps_y);
  381.         bumpVertex3f(Vx, Vy, Vz);
  382.  
  383.         /* v(i+1, j+1) */
  384.         Vy = (j + 1) * 200.f/steps_y - 100.f;
  385.         bumpNormal3f(Nx, Ny, Nz);
  386.         bumpTangent3f(Tx, Ty, Tz);
  387.         bumpTexCoord2f((i + 1)/(GLfloat)steps_xz, (j + 1)/(GLfloat)steps_y);
  388.         bumpVertex3f(Vx, Vy, Vz);
  389.  
  390.         /* v(i, j+1) */
  391.         c = cosf(M_PI * (1.f - (GLfloat)i/(steps_xz - 1)));
  392.         s = sinf(M_PI * (1.f - (GLfloat)i/(steps_xz - 1)));
  393.         Vx = 100 * c;
  394.         Vz = 100 * s - 100.f;
  395.         Nx = c;
  396.         Nz = s;
  397.         Tx = s;
  398.         Ty = -c;
  399.         bumpNormal3f(Nx, Ny, Nz);
  400.         bumpTangent3f(Tx, Ty, Tz);
  401.         bumpTexCoord2f(i/(GLfloat)steps_xz, (j + 1)/(GLfloat)steps_y);
  402.         bumpVertex3f(Vx, Vy, Vz);
  403.     }
  404.     glEnd();
  405.  
  406.     CHECK_ERROR("end of draw()");
  407. }
  408.  
  409.  
  410.  
  411. /* Called when window needs to be redrawn */
  412. void redraw_blendext(void)
  413. {
  414.     GLUquadricObj *obj;
  415.     void draw(void);
  416.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  417.  
  418.  
  419.     glLoadIdentity();
  420.  
  421.     gluLookAt(0., 0., 650., 0., 0., 0., 0., 1., 0.);
  422.     glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  423.  
  424.     glPushMatrix();
  425.     glTranslatef(lightpos[X], lightpos[Y], lightpos[Z]);
  426.     obj = gluNewQuadric();
  427.     gluSphere(obj, 7., 10, 10);
  428.     gluDeleteQuadric(obj);
  429.     glPopMatrix();
  430.  
  431.     glRotatef(angles[X], 0.f, 1.f, 0.f);
  432.     glRotatef(angles[Y], 1.f, 0.f, 0.f);
  433.  
  434.     if(textureOnly)
  435.     {
  436.     glEnable(GL_TEXTURE_2D);
  437.     draw();
  438.     glDisable(GL_TEXTURE_2D);
  439.     }
  440.     else if(lightOnly)
  441.     {
  442.     /* draw "z" diffuse component */
  443.     glEnable(GL_LIGHTING);
  444.     glEnable(GL_LIGHT0);
  445.     draw();
  446.     glDisable(GL_LIGHTING);
  447.     }
  448.     else /* bumpmapping */
  449.     {
  450.  
  451.     /* find N dot L */
  452.  
  453.     /* draw "z" diffuse component */
  454.     /* also do ambient here */
  455.     if(!embossed)
  456.     {
  457.         glEnable(GL_LIGHTING);
  458.         glEnable(GL_LIGHT0);
  459.         draw();
  460.         glDisable(GL_LIGHTING);
  461.     }
  462.     /* add in shifted values */
  463.     glEnable(GL_TEXTURE_2D);
  464.     glEnable(GL_BLEND);
  465.     glBlendFunc(GL_ONE, GL_ONE);
  466.     bumpEnable(); /* shift texture coords */
  467.     draw();
  468.     bumpDisable();
  469.  
  470. #ifdef GL_EXT_blend_subtract
  471.     /* subtract unshifted */
  472.     glBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
  473.     draw();
  474.     glBlendEquationEXT(GL_FUNC_ADD_EXT);
  475. #endif
  476.     glDisable(GL_BLEND);
  477.     glDisable(GL_TEXTURE_2D);
  478.  
  479.     if(color)
  480.     {
  481.         /* Modulate the color texture with N dot L */
  482.         glEnable(GL_TEXTURE_2D);
  483.         glEnable(GL_BLEND);
  484.         glBlendFunc(GL_DST_COLOR, GL_ZERO);
  485.         glBindTexture(GL_TEXTURE_2D, 1); /* use color texture */
  486.         draw();
  487.         glBindTexture(GL_TEXTURE_2D, 0);
  488.         glDisable(GL_BLEND);
  489.         glDisable(GL_TEXTURE_2D);
  490.     }
  491.  
  492.     }
  493.  
  494.     /* scale up the image */
  495.  
  496.     glPixelTransferf(GL_RED_SCALE, 2.f);
  497.     glPixelTransferf(GL_GREEN_SCALE, 2.f);
  498.     glPixelTransferf(GL_BLUE_SCALE, 2.f);
  499.     glCopyPixels(0, 0, winWidth, winHeight, GL_COLOR);
  500.  
  501.     CHECK_ERROR("OpenGL Error in redraw()");
  502.  
  503.     if(dblbuf)
  504.     glutSwapBuffers(); 
  505.     else
  506.     glFlush(); 
  507. }
  508.  
  509.  
  510. /* Called when window needs to be redrawn */
  511. void redraw_accum(void)
  512. {
  513.     GLUquadricObj *obj;
  514.     void draw(void);
  515.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  516.  
  517.  
  518.     glLoadIdentity();
  519.  
  520.     gluLookAt(0., 0., 650., 0., 0., 0., 0., 1., 0.);
  521.     glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  522.  
  523.     glRotatef(angles[X], 0.f, 1.f, 0.f);
  524.     glRotatef(angles[Y], 1.f, 0.f, 0.f);
  525.  
  526.     if(textureOnly)
  527.     {
  528.     glEnable(GL_TEXTURE_2D);
  529.     draw();
  530.     glDisable(GL_TEXTURE_2D);
  531.     }
  532.     else if(lightOnly)
  533.     {
  534.     /* draw "z" diffuse component */
  535.     glEnable(GL_LIGHTING);
  536.     glEnable(GL_LIGHT0);
  537.     draw();
  538.     glDisable(GL_LIGHTING);
  539.     }
  540.     else /* bumpmapping */
  541.     {
  542.  
  543.     CHECK_ERROR("start");
  544.     /* draw "z" diffuse component */
  545.     glEnable(GL_LIGHTING);
  546.     glEnable(GL_LIGHT0);
  547.     draw();
  548.     glAccum(GL_LOAD, .5f);
  549.     CHECK_ERROR("load");
  550.     glDisable(GL_LIGHTING);
  551.  
  552.     /* draw shifted */
  553.     glEnable(GL_TEXTURE_2D);
  554.     bumpEnable();
  555.     draw();
  556.     glAccum(GL_ACCUM, .5f);
  557.     bumpDisable();
  558.  
  559.     /* subtract unshifted */
  560.     draw();
  561.     glAccum(GL_ACCUM, -.5f);
  562.     
  563.     glDisable(GL_TEXTURE_2D);
  564.     glAccum(GL_RETURN, 2.f);
  565.  
  566.     if(color)
  567.     {
  568.         /* Modulate the color texture with N dot L */
  569.         glEnable(GL_TEXTURE_2D);
  570.         glEnable(GL_BLEND);
  571.         glBlendFunc(GL_DST_COLOR, GL_ZERO);
  572.         glBindTexture(GL_TEXTURE_2D, 1); /* use color texture */
  573.         draw();
  574.         glBindTexture(GL_TEXTURE_2D, 0);
  575.         glDisable(GL_BLEND);
  576.         glDisable(GL_TEXTURE_2D);
  577.     }
  578.  
  579.     }
  580.  
  581.     
  582.  
  583.     CHECK_ERROR("OpenGL Error in redraw()");
  584.  
  585.     glPushMatrix();
  586.     glLoadIdentity();
  587.     gluLookAt(0., 0., 650., 0., 0., 0., 0., 1., 0.);
  588.     glTranslatef(lightpos[X], lightpos[Y], lightpos[Z]);
  589.     obj = gluNewQuadric();
  590.     gluSphere(obj, 7., 10, 10);
  591.     gluDeleteQuadric(obj);
  592.     glPopMatrix();
  593.  
  594.  
  595.     if(dblbuf)
  596.     glutSwapBuffers(); 
  597.     else
  598.     glFlush(); 
  599. }
  600.  
  601. /* ARGSUSED1 */
  602. void key(unsigned char key, int x, int y)
  603. {
  604.     switch(key)
  605.     {
  606.     case 't':
  607.     if(textureOnly)
  608.         textureOnly = FALSE;
  609.     else
  610.         textureOnly = TRUE;
  611.     glutPostRedisplay();
  612.     break;
  613.     case 'l':
  614.     if(lightOnly)
  615.         lightOnly = FALSE;
  616.     else
  617.         lightOnly = TRUE;
  618.     glutPostRedisplay();
  619.     break;
  620.     case 'e':
  621.     if(embossed)
  622.         embossed = FALSE;
  623.     else
  624.         embossed = TRUE;
  625.     glutPostRedisplay();
  626.     break;
  627.     case 'B': /* make bumps taller */
  628.     bumpscale += .01f;
  629.     printf("bump map scale = %.2f\n", bumpscale);
  630.     glPixelTransferf(GL_RED_SCALE, bumpscale);
  631.     glPixelTransferf(GL_GREEN_SCALE, bumpscale);
  632.     glPixelTransferf(GL_BLUE_SCALE, bumpscale);
  633.  
  634.  
  635.     glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,
  636.              texture_width, texture_height, 0, GL_RGBA,
  637.              GL_UNSIGNED_BYTE, bumptex);
  638.     glutPostRedisplay();
  639.     break;
  640.     case 'b': /* make bumps flatter */
  641.     bumpscale -= .01f;
  642.     if(bumpscale < 0.f)
  643.         bumpscale = 0.f;
  644.     printf("bump map scale = %.2f\n", bumpscale);
  645.     glPixelTransferf(GL_RED_SCALE, bumpscale);
  646.     glPixelTransferf(GL_GREEN_SCALE, bumpscale);
  647.     glPixelTransferf(GL_BLUE_SCALE, bumpscale);
  648.  
  649.  
  650.     glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,
  651.              texture_width, texture_height, 0, GL_RGBA,
  652.              GL_UNSIGNED_BYTE, bumptex);
  653.     glutPostRedisplay();
  654.     break;
  655.     case 'c':
  656.     if(color == TRUE)
  657.         color = FALSE;
  658.     else
  659.         color = TRUE;
  660.     glutPostRedisplay();
  661.     break;
  662.     case 'w':
  663.     if(wire == TRUE)
  664.     {
  665.         glPolygonMode(GL_FRONT, GL_FILL);
  666.         wire = FALSE;
  667.     }
  668.     else
  669.     {
  670.         glPolygonMode(GL_FRONT, GL_LINE);
  671.         wire = TRUE;
  672.     }
  673.     glutPostRedisplay();
  674.     break;
  675.     case 'x':
  676.     steps_xz -= 2;
  677.     if(steps_xz < 1)
  678.         steps_xz = 1;
  679.     glutPostRedisplay();
  680.     break;
  681.     case 'X':
  682.     steps_xz += 2;
  683.     glutPostRedisplay();
  684.     break;
  685.     case 'y':
  686.     steps_y -= 2;
  687.     if(steps_y < 1)
  688.         steps_y = 1;
  689.     glutPostRedisplay();
  690.     break;
  691.     case 'Y':
  692.     steps_y += 2;
  693.     glutPostRedisplay();
  694.     break;
  695.     case '\033':
  696.     exit(0);
  697.     break;
  698.     case 'h':
  699.     case '?':
  700.     default:
  701.     fprintf(stderr, 
  702.         "Keyboard commands:\n"
  703.         "t-texture only\n"
  704.         "l-light only\n"
  705.         "c-color texture\n"
  706.         "e-embossed (horizontal part)\n"
  707.         "w-toggle wireframe\n"
  708.         "B-increase bumps b-decrease bumps\n");
  709.     break;
  710.     }
  711.  
  712. }
  713.  
  714.  
  715.  
  716. main(int argc, char *argv[])
  717. {
  718.     unsigned *tex;
  719.     GLfloat lightpos[4];
  720.     GLfloat diffuse[4];
  721.     GLboolean valid;
  722.     int texcomps, texwid, texht;
  723.     const char *version;
  724.     char varray[32];
  725.  
  726.     glutInit(&argc, argv);
  727.     glutInitWindowSize(winWidth, winHeight);
  728.     if(argc > 1)
  729.     {
  730.     char *args = argv[1];
  731.     int done = FALSE;
  732.     while(!done)
  733.     {
  734.         switch(*args)
  735.         {
  736.         case 's': /* single buffer */
  737.         printf("Single Buffered\n");
  738.         dblbuf = FALSE;
  739.         break;
  740.         case 'a': /* use accumulation buffer */
  741.         printf("Use accumulation buffer\n");
  742.         accum = TRUE;
  743.         break;
  744.         case '-': /* do nothing */
  745.         break;
  746.         case 0:
  747.         done = TRUE;
  748.         break;
  749.         }
  750.         args++;
  751.     }
  752.     }
  753.     if(dblbuf)
  754.     if(accum)
  755.         glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH|GLUT_ACCUM);
  756.         else
  757.         glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
  758.     else
  759.     if(accum)
  760.         glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_ACCUM);
  761.         else
  762.         glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH);
  763.  
  764.     (void)glutCreateWindow("bump mapping example program");
  765.     if(accum)
  766.     glutDisplayFunc(redraw_accum);
  767.     else
  768.     glutDisplayFunc(redraw_blendext);
  769.  
  770.     glutKeyboardFunc(key);
  771.     glutMouseFunc(mouse);
  772.     glutMotionFunc(motion);
  773.     glutReshapeFunc(reshape);
  774.  
  775.  
  776.     
  777.     version = (char *) glGetString(GL_VERSION);
  778.     strncpy(varray, version, strcspn(version, " "));
  779.     printf("%s\n", version);
  780.     if(atof(varray) > 1.f)
  781.     bindtex = TRUE;
  782.     else
  783.     bindtex = FALSE;
  784.  
  785.     glRasterPos3i(-1, -1, -1);
  786.     glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
  787.     if(!valid)
  788.     printf("invalid raster position!\n");
  789.     /* draw a perspective scene */
  790.     glMatrixMode(GL_PROJECTION);
  791.     glFrustum(-150., 150., -150., 150., 500., 800.);
  792.     glMatrixMode(GL_MODELVIEW);
  793.  
  794.     /* turn on features */
  795.     glEnable(GL_DEPTH_TEST);
  796.     glDepthFunc(GL_LEQUAL);
  797.  
  798.     /* remove back faces to speed things up */
  799.     glCullFace(GL_BACK);
  800.  
  801.  
  802.     diffuse[R] = diffuse[G] = diffuse[B] = .4f;
  803.     diffuse[A] = 1.f;
  804.     glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
  805.     bumptex = read_texture("data/ogllogo.bw", &texture_width, 
  806.                &texture_height, &texcomps);
  807.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  808.  
  809.     if(!accum)
  810.     {
  811.     /* scale to match maximum z (default Kd = .8, default Ld = 1. */
  812.     /* divide by 2 to stay in range of 0 to 1 */
  813.     glPixelTransferf(GL_RED_SCALE, bumpscale);
  814.     glPixelTransferf(GL_GREEN_SCALE, bumpscale);
  815.     glPixelTransferf(GL_BLUE_SCALE, bumpscale);
  816.     }
  817.  
  818.     glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,
  819.          texture_width, texture_height, 0, GL_RGBA,
  820.          GL_UNSIGNED_BYTE, bumptex);
  821.  
  822.     tex = read_texture("data/plank.rgb", &texwid, &texht, &texcomps);
  823.  
  824.     glBindTexture(GL_TEXTURE_2D, 1); /* for color */
  825.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  826.  
  827.     glPixelTransferf(GL_RED_SCALE, 1.f);
  828.     glPixelTransferf(GL_GREEN_SCALE, 1.f);
  829.     glPixelTransferf(GL_BLUE_SCALE, 1.f);
  830.  
  831.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
  832.          texwid, texht, 0, GL_RGBA,
  833.          GL_UNSIGNED_BYTE, tex);
  834.  
  835.     glBindTexture(GL_TEXTURE_2D, 0);
  836.  
  837.     free(tex);
  838.  
  839.     lightpos[X] = lightpos[Y] = 0.f;
  840.     lightpos[Z] = -90.f;
  841.     lightpos[W] = 1.f;
  842.     glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  843.     glDisable(GL_DITHER);
  844.  
  845.     CHECK_ERROR("end of main");
  846.  
  847.     if(!glutExtensionSupported("GL_EXT_blend_subtract")) {
  848.       fprintf(stderr,
  849.         "bump: requires OpenGL blend subtract extension to operate correctly.\n");
  850.     }
  851.  
  852.     key('?', 0, 0); /* startup message */
  853.     glutMainLoop();
  854.     return(0);
  855. }
  856.